package com.hk.core.service.elasticsearch.impl;

import co.elastic.clients.elasticsearch.core.search.FieldSuggester;
import com.hk.commons.query.Order;
import com.hk.commons.query.QueryModel;
import com.hk.commons.query.SortUtils;
import com.hk.commons.query.page.QueryPage;
import com.hk.commons.util.AssertUtils;
import com.hk.commons.util.CollectionUtils;
import com.hk.core.elasticsearch.query.Condition;
import com.hk.core.elasticsearch.repository.BaseElasticsearchRepository;
import com.hk.core.service.elasticsearch.ElasticSearchService;
import org.springframework.data.domain.Persistable;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.UnaryOperator;

/**
 * ElasticSearchServiceImpl
 *
 * @author kevin
 * @date 2019-6-28 11:40
 */
public abstract class ElasticSearchServiceImpl<T extends Persistable<ID>, ID extends Serializable>
        implements ElasticSearchService<T, ID> {

    protected abstract BaseElasticsearchRepository<T, ID> getBaseRepository();

    @Override
    public QueryPage<T> queryForPage(QueryModel<T> query) {
        return getBaseRepository().queryForPage(query);
    }

    @Override
    public long count(T t) {
        return getBaseRepository().count(t);
    }

    @Override
    public List<String> suggest(FieldSuggester suggester) {
        return getBaseRepository().suggest(suggester);
    }

    @Override
    public List<T> findAll(List<Condition> conditions, Order... orders) {
        return getBaseRepository().findAll(conditions, orders);
    }

    @Override
    public List<T> insertOrUpdate(Collection<T> entities) {
        return CollectionUtils.toList(getBaseRepository().saveAll(entities));
    }

    @Override
    public void deleteByIds(Iterable<ID> ids) {
        getBaseRepository().deleteByIds(ids);
    }

    @Override
    public QueryPage<T> queryForPage(List<Condition> conditions, int pageIndex, int pageSize, Order... orders) {
        return getBaseRepository().queryForPage(conditions, pageIndex, pageSize, orders);
    }

    @Override
    public void deleteById(ID id) {
        getBaseRepository().deleteById(id);
    }

    @Override
    public void delete(T entity) {
        getBaseRepository().delete(entity);
    }

    @Override
    public void delete(Iterable<T> entities) {
        getBaseRepository().deleteAll(entities);
    }

    @Override
    public T insert(T t, UnaryOperator<T> operator) {
        return getBaseRepository().save(operator.apply(t));
    }

    @Override
    public Collection<T> batchInsert(Iterable<T> entities) {
        return CollectionUtils.toCollection(getBaseRepository().saveAll(entities));
    }

    @Override
    public Optional<T> findById(ID id) {
        return getBaseRepository().findById(id);
    }

    @Override
    public List<T> findAll(Order... orders) {
        return CollectionUtils.toList(getBaseRepository().findAll(SortUtils.toSort(orders)));
    }

    @Override
    public List<T> findByIds(Iterable<ID> ids) {
        return CollectionUtils.toList(getBaseRepository().findAllById(ids));
    }

    @Override
    public boolean existsById(ID id) {
        return getBaseRepository().existsById(id);
    }

    @Override
    public boolean exists(T t) {
        ID id = t.getId();
        return Objects.nonNull(id) && getBaseRepository().existsById(id);
    }

    @Override
    public long count() {
        return getBaseRepository().count();
    }

    @Override
    public void bulkUpdate(Collection<T> entities) {
        getBaseRepository().bulkUpdate(entities);
    }

    @Override
    public T updateById(T t, UnaryOperator<T> function) {
        T entity = function.apply(t);
        AssertUtils.isTrue(!t.isNew(), "更新ID不能为空");
        return getBaseRepository().save(entity);
    }
}
